#ifndef MONITORDRIVER_H
#define MONITORDRIVER_H

#include <Globals.h>
#include <Lockable.h>
#include <Resource.h>

enum Colour
{
  black=0,
  blue=1,
  green=2,
  cyan=3,
  red=4,
  magenta=5,
  orange=6,
  lightGrey=7,
  darkGrey=8,
  lightBlue=9,
  lightGreen=10,
  lightCyan=11,
  lightRed=12,
  lightMagenta=13,
  yellow=14,
  white=15,
  none=16
};

enum Special
{
  endl,
  hex,
  dec
};

/**
  Syscall interface.
**/
namespace MonitorDriver_IF
{
  const int writeString   =0;
  const int writeHex      =1;
  const int writeDec      =2;
  const int put           =3;
  const int clear         =4;
  const int writeRaw      =5;
};

/**
  A statically compiled monitor driver. Writes to the screen in default text
  mode - 80x25 characters.
**/
class MonitorDriver : public Callable, public Lockable
{

public:

  MonitorDriver();

  ~MonitorDriver();

  void init();

  /**
    Writes a string out to the monitor
  **/
  void write(char *c, Colour foreColour=white, Colour backColour=black);

  void write(const char *c, Colour foreColour=white, Colour backColour=black)
  {
    write((char*)c,foreColour,backColour);  
  }
  void write1(const char *c)
  {
    write(c);
  }

  /**
    Writes a 32-bit signed integer as a hexadecimal number to the monitor
  **/
  void writeHex(s32int n, Colour foreColour=white, Colour backColour=black);
  void writeHex1(s32int n)
  {
    writeHex(n);
  }

  /**
    Writes a 32-bit signed integer as a decimal number to the monitor
  **/
  void writeDec(s32int n, Colour foreColour=white, Colour backColour=black);
  void writeDec1(s32int n)
  {
    writeDec(n);
  }

  /**
    Puts a character out to the monitor
  **/
  void put(char c, Colour foreColour=white, Colour backColour=black);
  void put1(char c)
  {
    put(c);
  }

  /**
    Clear the screen
  **/
  void clear();
  
  /**
    Memcpys the given framebuffer into the VGA ram, and sets the cursor
    position to that given.
  **/
  void writeRaw(u16int *ptr, u32int x, u32int y);
  
  /**
    Overloads << to print nicely.
  **/
  MonitorDriver &operator<<(char *c);
  MonitorDriver &operator<<(const char *c);
  MonitorDriver &operator<<(u32int i);
  MonitorDriver &operator<<(Special s);
  
  /**
    We are a system resource.
  **/
  Resource *resource;
  
private:
  /**
    Shifts all lines up one row if required.
  **/
  void scroll();
  
  /**
    Tells the video hardware to move the cursor
  **/
  void moveCursor();

  u16int *memoryLocation;
  u32int cursorX;
  u32int cursorY;
  
  /**
    Decimal or hex mode
  **/
  Special intMode;

};

#endif
